import axios, { AxiosInstance, AxiosResponse, AxiosRequestConfig, Canceler } from 'axios';
import store from '@/store';
import { storage } from '../Storage';
import { message } from 'ant-design-vue';
import { RequestEnum, responseStateEnum } from '@/enums/httpEnum';
import { UserActionTypes, MutationType } from '@/enums/userEnums';
import { LayoutMutationType } from '@/enums/layoutEnums';
import i18n from '@/i18n';

// 取消请求用的
const pendingMap = new Map<string, Canceler>();
const addPending = (url: string, cancel: Canceler) => {
    pendingMap.set(url, cancel);
};
const removePending = (url: string) => {
    pendingMap.delete(url);
};
export default (instance: AxiosInstance) => {
    instance.interceptors.request.use(
        (config: AxiosRequestConfig) => {
            if (pendingMap.has(config.url as string)) {
                const cancel = pendingMap.get(config.url as string);
                cancel && cancel();
                removePending(config.url as string);
            }
            config.cancelToken = new axios.CancelToken((c) => {
                addPending(config.url as string, c);
            });
            const token = storage.get(MutationType.SetToken, '');

            const lang = storage.get(LayoutMutationType.SetLang, 'zh');

            config.headers = Object.assign({}, config.headers, {
                Authorization: token,
            });

            config.headers = Object.assign({}, config.headers, {
                lang,
            });
            return config;
        },
        (err) => {
            return Promise.reject(err);
        }
    );
    // 返回结果拦截
    instance.interceptors.response.use(
        async (response: AxiosResponse) => {
            removePending(response.config.url as string);
            const { data } = response;

            return Promise.resolve(data);
        },
        (err) => {
            const errMsg = err.response?.data?.message ? err.response.data.message : err;

            if (axios.isCancel(err)) {
                return err;
            }
            // 登录Token失效
            if (err.response?.status === responseStateEnum.UNAUTHORIZED) {
                store.dispatch(UserActionTypes.Logout);
            }

            if (errMsg) {
                message.error(errMsg);
            }
            if (errMsg.toString().indexOf('timeout') !== -1) {
                message.error(i18n.global.t('yl.requestTimeout'));
                const { config } = err.config;
                let __retryCount = config?.__retryCount ? config.__retryCount : 0;

                __retryCount += 1;

                const backoff = new Promise((resolve) => {
                    setTimeout(() => {
                        resolve(config);
                    }, __retryCount || 1);
                });

                return backoff.then(() => {
                    return axios(config);
                });
            }

            return Promise.reject(err);
        }
    );
};
